#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <semaphore.h>

#define N 128

int main(int argc, char const *argv[])
{
    sem_t *sem;
    remove("/dev/shm/sem.sem");

    //创建一个信号量
    sem = sem_open("sem", O_RDWR | O_CREAT, 0664, 1);
    if (sem == SEM_FAILED)
    {
        perror("sem_open");
        exit(-1);
    }

    int value;
    sem_getvalue(sem, &value);
    printf("value=%d\n", value);

    // 1. 生成一个IPC 唯一key值
    key_t key = ftok("/home", 1);
    if (key < 0)
    {
        perror("key");
        exit(-1);
    }
    printf("key=%#x\n", key);
    int shmid = shmget(key, N, IPC_CREAT | 0664); //如果不存在就创建，存在就打开
    if (shmid < 0)
    {
        perror("shmid");
        exit(-1);
    }
    printf("shmid=%d\n", shmid);
    system("ipcs -m"); //执行linux系统的一个命令 查看系统的共享内存

    void *shmaddr = shmat(shmid, NULL, 0); //把共享内存映射到进程内，进程就可以访问这段内存了
    if (shmaddr == (void *)-1)
    {
        perror("shmaddr");
        exit(-1);
    }
    system("ipcs -m"); //执行linux系统的一个命令 查看系统的共享内存

    memset(shmaddr, 0, N); //对共享内存进行清空

    pid_t pid = fork();
    if (pid < 0)
    {
        perror("pid");
        exit(-1);
    }
    else if (pid == 0)
    {
        while (1)
        {
            sem_wait(sem);
            memset(shmaddr, 'O', 64); //对共享内存进行操作，写入128个O
            usleep(1000);
            memset(shmaddr + 64, 'O', 63); //对共享内存进行操作，写入128个O
            sem_post(sem);
        }
    }
    else
    {
        while (1)
        {
            sem_wait(sem);
            memset(shmaddr, '-', 64); //对共享内存进行操作，写入128个O
            usleep(1000);
            memset(shmaddr + 64, '-', 63); //对共享内存进行操作，写入128个O
            sem_post(sem);
        }
    }

    int ret = shmdt(shmaddr);
    if (ret < 0)
    {
        perror("ret");
        exit(-1);
    }
    system("ipcs -m"); //执行linux系统的一个命令 查看系统的共享内存

    ret = shmctl(shmid, IPC_RMID, NULL);
    if (ret < 0)
    {
        perror("ret");
        exit(-1);
    }
    system("ipcs -m"); //执行linux系统的一个命令 查看系统的共享内存

    return 0;
}
